# import packages
from keras.layers import Conv2D, MaxPooling2D
from keras.models import Sequential
from keras import layers
from keras import Sequential, optimizers
from keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions
from keras.layers import Dense, Flatten
from keras.models import Model
from keras import models
from keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array
import keras
from sklearn.metrics import confusion_matrix
from sklearn.naive_bayes import MultinomialNB
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import silhouette_score, adjusted_rand_score, silhouette_samples
from sklearn.cluster import DBSCAN, AgglomerativeClustering, KMeans
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
from sklearn import preprocessing
from scipy.spatial import distance
from scipy import ndimage
from keras.preprocessing.image import ImageDataGenerator
import imutils
import PIL
import cv2
from collections import Counter
import collections
from scipy.stats import variation
from scipy import stats
from scipy.stats.stats import pearsonr
import scipy.stats as stats
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure
import matplotlib
import missingno as msno
import pickle
#import mss
import os
from os import listdir
import pandas as pd
import numpy as np
import re
import math
from termcolor import colored
from datetime import datetime
from datetime import timedelta
import warnings
warnings.filterwarnings('ignore')
pd.options.mode.chained_assignment = None
pd.options.display.width = 0
%matplotlib inline
# Format & option.
sns.set(rc={'figure.figsize': (16, 9)})
pd.options.display.max_columns = 50
# Style use.
sns.set_style('darkgrid')
plt.style.use('ggplot')
def clustering(algo, data, true_category, label_true_category, algo_name, file_name=None):
print(colored("Exécution \n ", 'red'))
model = algo.fit(data)
if file_name is None:
pass
else :
# save the model to disk
filename = file_name
pickle.dump(model, open(filename, 'wb'))
label_model = model.labels_
lines = model.labels_.shape[0]
print(colored(
"Nombre de lignes pris en compte pour le clustering {} \n \n".format(lines), 'blue'))
labels = pd.DataFrame(label_model, columns=['algo_cluster'])
mylist = list(set(label_model))
nb_cluster = len(mylist)
print(colored("Qualité du Clustering \n \n ", 'red'))
# mean Silhouette Coefficient of all samples
""" label = model.labels_
unique, counts = np.unique(label, return_counts=True)
print(unique)"""
silhouette = silhouette_score(X=data, labels=model.labels_)
print(colored('Le coefficient de silhouette moyen est de {} pour la méthode {}.\n \n '.format(
silhouette, algo_name), 'blue'))
tot_data_label = pd.concat([true_category, label_true_category, labels], axis=1, names=[
'category', 'label_category', 'algo_cluster'])
tot_data_label.reset_index(drop=True)
# Indice de Rand ajusté.
ARI = adjusted_rand_score(
tot_data_label['label_category'], tot_data_label['algo_cluster'])
print(colored('Le score ARI est de {} pour la méthode {}. \n \n'.format(
ARI, algo_name), 'blue'))
print(colored("Visualisation \n \n ", 'red'))
tsne = TSNE(n_components=2, init="pca")
X_trans = tsne.fit_transform(data)
plt.figure(figsize=(10, 10))
plt.title(
"TSNE selon les clusters via {}.\n" .format(algo_name), fontsize=30)
sns.scatterplot(
X_trans[:, 0],
X_trans[:, 1],
hue=model.labels_,
legend="brief",
palette=sns.color_palette("husl", nb_cluster),
)
sns.set_context("paper", font_scale=1)
plt.xlabel("tsne1")
plt.xlabel("tsne2")
plt.show()
print("ARI : ", adjusted_rand_score(tot_data_label['label_category'], tot_data_label['algo_cluster']))
print('\n \n')
from matplotlib import rcParams
rcParams['axes.titlepad'] = 40
values = tot_data_label['algo_cluster'].value_counts()
labels = tot_data_label['algo_cluster'].value_counts().index
#color = ['gold', 'pink', 'grey', 'orange', 'green', 'blue', 'purple', 'yellow', 'red', 'brown', 'violet']
#colors = color[:nb_cluster]
# Plot
from matplotlib import cm
cs = cm.Set2(np.arange(nb_cluster))
plt.figure(figsize=(10, 10))
plt.pie(values, labels=labels, colors=cs,
autopct='%.2f%%', shadow=True, textprops={'fontsize': 24})
plt.title(
"Répartition des produits entre les différentes catégories déterminées par l'algorithme {}" .format(algo_name), fontsize=30)
plt.axis('equal')
plt.tight_layout()
plt.show()
return silhouette, ARI, tot_data_label
def classification(best_param, X_train, y_train, X_test, y_test, algo_name, file_name=None):
print(colored("Exécution \n ", 'red'))
model = best_param.fit(X_train, y_train)
if file_name is None:
pass
else :
# save the model to disk
filename = file_name
pickle.dump(model, open(filename, 'wb'))
prediction = best_param.predict(X_test)
df = pd.DataFrame(prediction, columns=['prediction'])
resume_class = pd.concat([y_test, df], axis=1)
print(colored("Qualité de la classification \n \n ", 'red'))
accuracy = accuracy_score(y_test, prediction)
print(colored('L\'accuracy score est de {} pour la méthode {}.\n \n '.format(
accuracy, algo_name), 'blue'))
precision = precision_score(y_test, prediction, average='weighted')
print(colored('Le score de précision est de {} pour la méthode {}.\n \n '.format(
precision, algo_name), 'blue'))
recall = recall_score(y_test, prediction, average='weighted')
print(colored('Le score recall est de {} pour la méthode {}.\n \n '.format(
recall, algo_name), 'blue'))
f1 = f1_score(y_test, prediction, average='weighted')
print(colored('Le score f1 est de {} pour la méthode {}.\n \n '.format(
f1, algo_name), 'blue'))
le = preprocessing.LabelEncoder()
resume_class['label_cat_reel'] = le.fit_transform(
np.array(resume_class['product_category']))
resume_class['label_cat_predit'] = le.transform(
np.array(resume_class['prediction']))
print(colored("Visualisation \n \n ", 'red'))
plt.figure(figsize=(10, 10))
plt.title('Répartition des catégories après classification par la méthode {}.\n \n '.format(
algo_name), fontsize=18, fontweight="bold")
sns.distplot(resume_class['label_cat_reel'], bins=20, rug=True)
sns.distplot(resume_class['label_cat_predit'], bins=20, rug=True)
plt.xlabel("Catégories")
plt.legend(['reel', 'prediction'])
from matplotlib import cm
fig = plt.figure(figsize=(30, 15))
ax1 = plt.subplot(121)
ax2 = plt.subplot(122)
nb_label_real = resume_class['product_category'].nunique()
cs_nb_label_real = cm.Set2(np.arange(nb_label_real))
nb_label_predit = resume_class['prediction'].nunique()
cs_nb_label_predit = cm.Set2(np.arange(nb_label_predit))
ax1 = resume_class.groupby('product_category').count().plot(kind='pie',
y='label_cat_reel',
ax=ax1,
legend=False,
shadow=True,
startangle=0,
autopct='%1.1f%%',
textprops={
'fontsize': 26},
colors=cs_nb_label_real)
ax1.axis('equal')
ax1.set_xlabel("classes réelles", fontsize=22)
ax1.set_ylabel(" ")
ax2 = resume_class.groupby('prediction').count().plot(kind='pie',
y='label_cat_predit',
ax=ax2,
legend=False,
shadow=True,
startangle=0,
autopct='%1.1f%%',
textprops={
'fontsize': 26},
colors=cs_nb_label_predit)
ax2.axis('equal')
ax2.set_xlabel("classes prédites par {}" .format(
algo_name), fontsize=22)
ax2.set_ylabel(" ")
plt.suptitle('Répartition des produits (test data) entre les différentes catégories déterminées',
fontsize=30)
plt.subplots_adjust(wspace=1.5)
plt.show()
cf_matrix = confusion_matrix(
resume_class["product_category"], resume_class["prediction"], normalize='true')
plt.figure(figsize=(18, 12))
plt.title('Matrice de confusion', size=20, weight='bold')
sns.set(font_scale=1.4) # for label size
sns.heatmap(cf_matrix, annot=True,
fmt='.2%', cmap='BuPu',
annot_kws={"size": 15, 'weight': 'bold'})
plt.ylabel("Vraie catégorie", weight='bold', size=20)
plt.xlabel('Prediction', weight='bold', size=17)
plt.show()
return accuracy, precision, recall, f1, resume_class
from google.colab import drive
drive.mount('/content/drive')
%cd / content/drive/My\ Drive/Data_projet_OC
!ls
data = pd.read_csv(
'/content/drive/MyDrive/Data_projet_OC/Flipkart/flipkart_com-ecommerce_sample_1050.csv')
"""data = pd.read_csv(
"/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC"
"/WORK-projet6/Data/Flipkart/flipkart_com-ecommerce_sample_1050.csv")"""
def remove_columns(dataframe):
new = pd.DataFrame()
columns_to_keep = [
'uniq_id', 'product_name', 'image', 'product_category_tree']
for column in columns_to_keep:
try:
new[column] = dataframe[column]
except:
print('...colonne non présente : ', column)
print('\n')
print("All selected columns have been kept from the dataset")
return new
data_clean = remove_columns(data)
def recover_root_cat(column):
categorie = column.split('["')[1].split('"]')[0]
cat = categorie.split(' >> ')[0]
return cat
data_clean['product_category'] = data_clean['product_category_tree'].apply(
recover_root_cat)
data_clean['product_category'] = data_clean['product_category'].str.replace(
' ', '_')
data_clean['product_category'] = data_clean['product_category'].str.replace(
'&', 'and')
data_clean['product_category'] = data_clean['product_category'].str.lower()
# Encodage des catégories trouvées manuellement
le = preprocessing.LabelEncoder()
data_clean['label_product_category'] = le.fit_transform(
np.array(data_clean['product_category']))
data_clean['product_category'].unique()
data_clean.head()
# correspondance
data_clean.loc[data_clean['label_product_category'] == 0]
print('Le label 0 correspond à la catégorie baby_care')
data_clean.loc[data_clean['label_product_category'] == 1]
print('Le label 1 correspond à la catégorie beauty_and_personal_care')
data_clean.loc[data_clean['label_product_category'] == 2]
print('Le label 2 correspond à la catégorie computers')
data_clean.loc[data_clean['label_product_category'] == 3]
print('Le label 3 correspond à la catégorie home_decor_&_festive_needs')
data_clean.loc[data_clean['label_product_category'] == 4]
print('Le label 4 correspond à la catégorie home_furnishing')
data_clean.loc[data_clean['label_product_category'] == 5]
print('Le label 5 correspond à la catégorie kitchen_&_dining')
data_clean.loc[data_clean['label_product_category'] == 6]
print('Le label 6 correspond à la catégorie watches')
Pillow n'étant plus mis à jour, je décide d'utiliser la bibliothèque opencv-python et en particulier cv2 pour le traitement d'image.
Le preprocessing sur les images s'articule comme suit:
Extraction des descripteurs de l'image par l'algorithme ORB.
ORB est aussi performant que SIFT pour la détection des caractéristiques (et est meilleur que SURF) tout en étant presque deux ordres de grandeur plus rapide.
from PIL import Image
# Charger l'image
"""img = Image.open(
"/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/cheval.png")"""
img = Image.open(
"/content/drive/MyDrive/Data_projet_OC/cheval.png")
# Afficher l'image chargée
img.show()
# Récupérer et afficher la taille de l'image (en pixels)
w, h = img.size
print("Largeur : {} px, hauteur : {} px".format(w, h))
Ce résultat signifie que l'image analogique a été découpée en 800 pixels sur la largeur et 533 pixels sur la hauteur pendant l'échantillonnage.
"""data = open(
'/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/cheval.png', 'rb').read()"""
data = open(
'/content/drive/MyDrive/Data_projet_OC/cheval.png', 'rb').read()
image_array_horse = np.asarray(bytearray(data), dtype="uint8")
print(f'Shape of the image {image_array_horse.shape}')
image_horse = cv2.imdecode(image_array_horse, cv2.IMREAD_COLOR)
plt.axis('off')
# opencv if BGR color, matplotlib usr RGB so we need to switch
plt.imshow(cv2.cvtColor(image_horse, cv2.COLOR_BGR2RGB))
plt.show()
# Transformation de l'image de 3D en 1D
res = cv2.resize(image_horse, dsize=(40, 40), interpolation=cv2.INTER_CUBIC)
print(res.shape)
res = cv2.cvtColor(res, cv2.COLOR_RGB2GRAY) # TO 3D to 1D
print(res.shape)
# séparation en blanc et noir, côté gauche = noir, côté droit = blanc
res = cv2.threshold(res, 127, 255, cv2.THRESH_BINARY)[1]
# Si la valeur du pixel est inférieure au seuil, elle est fixée à 0, sinon elle est fixée à une valeur maximale.
d = res
for row in range(0, 40):
for col in range(0, 40):
print('%03d ' % d[row][col], end=' ')
print('')
plt.imshow(cv2.cvtColor(res, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.show()
# Ctransformation de l'image en noir et blanc
img_bw = cv2.imdecode(image_array_horse, cv2.IMREAD_GRAYSCALE)
plt.axis('off')
plt.imshow(cv2.cvtColor(img_bw, cv2.COLOR_BGR2RGB))
"""(thresh, img_bw) = cv2.threshold(img_bw, 127, 255, cv2.THRESH_BINARY)
plt.axis('off')
plt.imshow(cv2.cvtColor(img_bw, cv2.COLOR_BGR2RGB))"""
Le premier argument est l'image source, qui doit être une image en niveaux de gris. Le deuxième argument est la valeur de seuil qui est utilisée pour classer les valeurs de pixels. Le troisième argument est la valeur maximale qui est attribuée aux valeurs de pixels dépassant le seuil.
plt.figure(figsize=(16, 9))
plt.title("Histogramme de l'image en niveau de gris", weight='bold', size=20)
n, bins, patches = plt.hist(img_bw.flatten(), bins=range(256))
plt.show()
à gauche se situent les pixels noirs, à droite les pixels blancs, et au milieu, toutes les nuances de gris
étirement d'histogramme = corriger les défauts liés à l’exposition d'une image = l'objectif est d'étendre les valeurs des niveaux de gris de l'image mal exposée, majoritairement réparties dans un sous intervalle [Imin,Imax]⊂[0,255].
def autocontrast_func(img, cutoff=0):
'''
same output as PIL.ImageOps.autocontrast
'''
n_bins = 256
def tune_channel(ch):
n = ch.size
cut = cutoff * n // 100
if cut == 0:
high, low = ch.max(), ch.min()
else:
hist = cv2.calcHist([ch], [0], None, [n_bins], [0, n_bins])
low = np.argwhere(np.cumsum(hist) > cut)
low = 0 if low.shape[0] == 0 else low[0]
high = np.argwhere(np.cumsum(hist[::-1]) > cut)
high = n_bins - 1 if high.shape[0] == 0 else n_bins - 1 - high[0]
if high <= low:
table = np.arange(n_bins)
else:
scale = (n_bins - 1) / (high - low)
offset = -low * scale
table = np.arange(n_bins) * scale + offset
table[table < 0] = 0
table[table > n_bins - 1] = n_bins - 1
table = table.clip(0, 255).astype(np.uint8)
return table[ch]
channels = [tune_channel(ch) for ch in cv2.split(img)]
out = cv2.merge(channels)
return out
img_et = autocontrast_func(img_bw)
plt.axis('off')
plt.imshow(cv2.cvtColor(img_et, cv2.COLOR_BGR2RGB))
plt.figure(figsize=(16, 9))
plt.title("Histogramme de l'étirement d’histogrammes", weight='bold', size=20)
n, bins, patches = plt.hist(img_et.flatten(), bins=range(256))
plt.show()
les pixels se répartissent bien dans tout l'intervalle [0,255] et l'image présente une meilleure luminosité
égalisation d'histogrammes = amélioration du contraste de l'image = réajuster le contraste d'une image = harmoniser la distribution des niveaux de gris de l'image, de sorte que chaque niveau de l'histogramme contienne idéalement le même nombre de pixels. Concrètement, on essaye d'aplatir au maximum l'histogramme original.
image = cv2.equalizeHist(img_et) # equalize image histogram
plt.axis('off')
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.figure(figsize=(16, 9))
plt.title("Histogramme de l'égalisation d’histogrammes",
weight='bold', size=20)
n, bins, patches = plt.hist(image.flatten(), bins=range(256))
plt.show()
L'image est plus contrastée et son histogramme confirme que la distribution de ses niveaux de gris est plus uniforme.
lissage par moyennage = remplacer la valeur de chaque pixel par l'intensité moyenne de son voisinage
image_denoise = cv2.fastNlMeansDenoising(image)
plt.axis('off')
plt.imshow(cv2.cvtColor(image_denoise, cv2.COLOR_BGR2RGB))
plt.figure(figsize=(16, 9))
plt.title("Histogramme de débruitage", weight='bold', size=20)
n, bins, patches = plt.hist(image_denoise.flatten(), bins=range(256))
plt.show()
Le bruit est bien atténué, mais en contrepartie, l'image est devenue floue
# defining an identity kernel, will change nothing because each pixel will remain with is value
kernel = np.matrix([[0, 0, 0], [0, 1, 0], [0, 0, 0]])
print(kernel)
img_1 = cv2.filter2D(image_denoise, -1, kernel)
plt.axis('off')
plt.imshow(cv2.cvtColor(img_1, cv2.COLOR_BGR2RGB))
# defining a vertical edge detection kernel
kernel = np.matrix([[-10, 0, 10], [-10, 0, 10], [-10, 0, 10]])
print(kernel)
img_1 = cv2.filter2D(image_denoise, -1, kernel)
plt.axis('off')
plt.imshow(cv2.cvtColor(img_1, cv2.COLOR_BGR2RGB))
# defining an horizontal edge detection kernel
kernel = np.matrix([[10, 10, 10], [0, 0, 0], [-10, -10, -10]])
print(kernel)
img_1 = cv2.filter2D(image_denoise, -1, kernel)
plt.axis('off')
plt.imshow(cv2.cvtColor(img_1, cv2.COLOR_BGR2RGB))
from scipy.ndimage import convolve
m = [[-10, 0, 10], [-10, 0, 10], [-10, 0, 10]]
k = [[10, 10, 10], [0, 0, 0], [-10, -10, -10]]
c = convolve(m, k, mode='constant', cval=0.0)
print('Matrix')
print('\n'.join([''.join(['{:4}'.format(item) for item in row])
for row in m]))
print('Kernel')
print('\n'.join([''.join(['{:4}'.format(item) for item in row])
for row in k]))
print('Convolution')
print('\n'.join([''.join(['{:4}'.format(item) for item in row])
for row in c]))
k2 = np.matrix(k)
f_min, f_max = k2.min(), k2.max()
filter = (k2 - f_min) / (f_max - f_min)
print(k2.shape)
fig = plt.figure(figsize=(3, 3))
plt.imshow(k2)
plt.show
il s'agit de filtres dont le fonctionnement ne peut être défini comme un produit de convolution = la valeur de chaque pixel est remplacée par la médiane (et non la moyenne) de son voisinage
image_filtre_1 = cv2.medianBlur(image_denoise, 3)
plt.axis('off')
plt.imshow(cv2.cvtColor(image_filtre_1, cv2.COLOR_BGR2RGB))
plt.figure(figsize=(16, 9))
plt.title("Histogramme filtre médian", weight='bold', size=20)
n, bins, patches = plt.hist(image_filtre_1.flatten(), bins=range(256))
plt.show()
Un filtre gaussien est un filtre linéaire dont les éléments du noyau de convolution sont déterminés selon la densité d'une loi gaussienne = c'est un filtre basé sur la moyenne : chaque pixel est corrigé avec une moyenne dont les poids ont des valeurs différentes
image_filtre_2 = cv2.GaussianBlur(image_filtre_1, (5, 5), 1)
plt.axis('off')
plt.imshow(cv2.cvtColor(image_filtre_2, cv2.COLOR_BGR2RGB))
plt.figure(figsize=(16, 9))
plt.title("Histogramme filtre gausien", weight='bold', size=20)
n, bins, patches = plt.hist(image_filtre_1.flatten(), bins=range(256))
plt.show()
# OpenCV 3 backward incompatibility: Do not create a detector with `cv2.ORB()`.
orb = cv2.ORB_create()
key_points, description = orb.detectAndCompute(image_filtre_2, None)
img_building_keypoints = cv2.drawKeypoints(image_filtre_2,
key_points,
image_filtre_2,
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # Draw circles.
plt.figure(figsize=(16, 16))
plt.title('ORB Interest Points')
plt.imshow(img_building_keypoints)
plt.show()
L'objectif final est d'avoir un training et un testing set à partir des images.
Un Bag of Visual Word est réalisé à l'aide de l'algorithme ORB. On cherchera à optimiser le nombre de Visual Word créé en utilisant un algorithme de classification k-means.
BoVW est une technique couramment utilisée dans la classification des images. L'idée derrière cette technique est similaire à celle du sac de mots du langage naturel, mais dans cette technique, nous utilisons les caractéristiques de l'image comme des mots.
1) Nous extrayons les caractéristiques locales de plusieurs images en utilisant SIFT ou ORB.
2) Quantifier l'espace des caractéristiques. Effectuer cette opération via des algorithmes de clustering tel que K-means. Les points centraux, que nous obtenons de l'algorithme de clustering, sont nos mots visuels.
3) Extraire les caractéristiques locales et les comparer aux mots visuels afin de créer des histogrammes pour chaque image, à la fois pour l'ensemble de données de test et d'entraînement.
Pour chaque image passage en gris et equalisation
création d'une liste de descripteurs par image ("sift_keypoints_by_img") qui sera utilisée pour réaliser les histogrammes par image
création d'une liste de descripteurs pour l'ensemble des images ("sift_keypoints_all") qui sera utilisée pour créer les clusters de descripteurs
ORB : ORB est fondamentalement une fusion du détecteur de keyspoints FAST et du descripteur BRIEF avec de nombreuses modifications pour améliorer les performances. Il utilise d'abord la FAST pour trouver les points clés, puis applique la mesure des coins de Harris pour trouver les N meilleurs points parmi eux.
"""# Liste contenant les descripteurs.
sift_keypoints = []
path = "/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/Flipkart/Images/"
#path = "/content/drive/MyDrive/Data_projet_OC/Flipkart/Images/
# Extraction des descripteurs par orb
sift = cv2.SIFT_create()
for image_num in range(len(list_name_pictures)) :
if image_num%100 == 0 : print(image_num)
image_bw = cv2.imread(path+list_name_pictures[image_num],0) # convert in grey
image_bw_resized = imutils.resize(image_bw, width=400)# convert all picture to the same size
# Amélioration luminosité
#img_lum = autocontrast_func(image_bw_resized)
# Amélioration contraste
#image_cont = cv2.equalizeHist(img_lum) # égalisation histogramme
image_cont = cv2.equalizeHist(image_bw_resized) # égalisation histogramme
# Débruitage
image_denoise = cv2.fastNlMeansDenoising(image_cont)
# Filtre médian
image_filtre_1 = cv2.medianBlur(image_denoise, 3)
#image_filtre_1 = cv2.medianBlur(image_cont, 3)
# filtre gausien
image_filtre_2 = cv2.GaussianBlur(image_filtre_1, (5, 5), 1)
# Keypoints & Descripteurs.
key_points, description = sift.detectAndCompute(image_filtre_2, None)
#img = cv2.drawKeypoints(i,kp,i)
sift_keypoints.append(description)
sift_keypoints_by_img = np.asarray(sift_keypoints)
sift_keypoints_all = np.concatenate(sift_keypoints_by_img, axis=0)
print("\n \n Nombre de descripteurs : ", sift_keypoints_all.shape[0]) """
# Liste contenant les descripteurs.
sift_keypoints = []
"""path = "/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/Flipkart/Images"""
folder = "/content/drive/MyDrive/Data_projet_OC/Flipkart/Images"
# Extraction des descripteurs par orb
orb = cv2.ORB_create()
name_img = []
"""for image_num in range(len(list_name_pictures)):
if image_num % 100 == 0:
print(image_num)
name_img.append(list_name_pictures[image_num])
image_bw = cv2.imread(
path+list_name_pictures[image_num], 0) # convert in grey"""
# Boucle pour charger les images.
for img in os.listdir(folder):
# Path.
path = folder + '/' + img
name_img.append(img)
# Chargement des images et sizing à 224*224 pixels.
image_bw = cv2.imread(path, 0) # convert in gre
# convert all picture to the same size
image_bw_resized = imutils.resize(image_bw, width=400)
# Amélioration luminosité
#img_lum = autocontrast_func(image_bw_resized)
# Amélioration contraste
# image_cont = cv2.equalizeHist(img_lum) # égalisation histogramme
image_cont = cv2.equalizeHist(image_bw_resized) # égalisation histogramme
# Débruitage
image_denoise = cv2.fastNlMeansDenoising(image_cont)
# Filtre médian
#image_filtre_1 = cv2.medianBlur(image_denoise, 3)
#image_filtre_1 = cv2.medianBlur(image_cont, 3)
# filtre gausien
#image_filtre_2 = cv2.GaussianBlur(image_filtre_1, (5, 5), 1)
image_filtre_2 = cv2.GaussianBlur(image_denoise, (5, 5), 1)
# Keypoints & Descripteurs.
key_points, description = orb.detectAndCompute(image_filtre_2, None)
#img = cv2.drawKeypoints(i,kp,i)
sift_keypoints.append(description)
sift_keypoints_by_img = np.asarray(sift_keypoints)
sift_keypoints_all = np.concatenate(sift_keypoints_by_img, axis=0)
print("\n \n Nombre de descripteurs : ", sift_keypoints_all.shape[0])
df_order_image = pd.DataFrame(name_img)
df_order_image.columns = ['image']
df_order_image
data_clean_ordered = pd.merge(
df_order_image, data_clean, left_on='image', right_on='image')
data_clean_ordered.head()
final_data = pd.DataFrame()
final_data['image'] = data_clean_ordered['image']
final_data['category'] = data_clean_ordered['product_category']
final_data['label_category'] = data_clean_ordered['label_product_category']
final_data
from matplotlib.image import imread
list_labels = ["baby_care", "beauty_and_personal_care", "computers",
"home_decor_and_festive_needs", "home_furnishing", "kitchen_and_dining", "watches"]
def list_fct(name):
list_image_name = [name_img[i]
for i in range(len(final_data)) if final_data["category"][i] == name]
return list_image_name
list_baby_care = [name_img[i] for i in range(
len(final_data)) if final_data["category"][i] == "baby_care"]
list_bepc = [name_img[i] for i in range(
len(final_data)) if final_data["category"][i] == "beauty_and_personal_care"]
list_computers = [name_img[i] for i in range(
len(final_data)) if final_data["category"][i] == "computers"]
list_hdfn = [name_img[i] for i in range(
len(final_data)) if final_data["category"][i] == "home_decor_and_festive_needs"]
list_home_furnishing = [name_img[i] for i in range(
len(final_data)) if final_data["category"][i] == "home_furnishing"]
list_kd = [name_img[i] for i in range(
len(final_data)) if final_data["category"][i] == "kitchen_and_dining"]
list_watches = [name_img[i]
for i in range(len(final_data)) if final_data["category"][i] == "watches"]
path = "/content/drive/MyDrive/Data_projet_OC/Flipkart/Images/"
for name in list_labels:
print(name)
# print("-------")
for i in range(3):
plt.subplot(130 + 1 + i)
filename = path + list_fct(name)[i+10]
image = imread(filename)
plt.imshow(image)
plt.show()
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
file_name = "sift_keypoints_by_img_total.pkl"
open_file = open(file_name, "wb")
pickle.dump(sift_keypoints_by_img, open_file)
open_file.close()
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
open_file = open(file_name, "rb")
sift_keypoints_by_img = pickle.load(open_file)
open_file.close()
# print(sift_keypoints_by_img)
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
file_name1 = "sift_keypoints_all_total.pkl"
open_file1 = open(file_name1, "wb")
pickle.dump(sift_keypoints_all, open_file1)
open_file1.close()
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
open_file1 = open(file_name1, "rb")
sift_keypoints_all = pickle.load(open_file1)
open_file1.close()
# print(sift_keypoints_all)
Envoyer le dictionnaire visuel à l'algorithme de clustering k-means et trouver les mots visuels qui sont des points centraux.
from sklearn import cluster, metrics
# Determination number of clusters
k = int(round(np.sqrt(len(sift_keypoints_all)), 0))
print("Nombre de clusters estimés : ", k)
print("Création de", k, "clusters de descripteurs ...")
# Clustering
# MiniBatchKMeans k-means plus rapide argument en plus : init_size=3*k
kmeans = cluster.MiniBatchKMeans(
n_clusters=k, random_state=0, init='k-means++', init_size=3*k)
kmeans.fit(sift_keypoints_all)
Features d'une image = Histogramme d'une image = Comptage pour une image du nombre de descripteurs par cluster
# Creation of histograms (features)
def build_histogram(kmeans, des, image_num):
res = kmeans.predict(des)
hist = np.zeros(len(kmeans.cluster_centers_))
nb_des = len(des)
if nb_des == 0:
print("problème histogramme image : ", image_num)
for i in res:
hist[i] += 1.0/nb_des
return hist
# Creation of a matrix of histograms
hist_vectors = []
for i, image_desc in enumerate(sift_keypoints_by_img):
if i % 100 == 0:
print(i)
hist = build_histogram(kmeans, image_desc, i) # calculates the histogram
hist_vectors.append(hist) # histogram is the feature vector
im_features = np.asarray(hist_vectors)
im_features
unique_rows = np.unique(im_features, axis=0)
unique_rows
file_name2 = "im_features.pkl"
open_file2 = open(file_name2, "wb")
pickle.dump(im_features, open_file2)
open_file2.close()
open_file2 = open(file_name2, "rb")
im_features = pickle.load(open_file2)
open_file2.close()
# print(sift_keypoints_all)
df_visual_word_total = pd.DataFrame(im_features)
df_visual_word_total
# sur google colab
from google.colab import drive
drive.mount('/content/drive')
df_visual_word_total.to_csv('df_visual_word_total.csv', index=False)
!cp df_visual_word_total.csv /content/drive/My\ Drive/
"""df_visual_word_total.to_csv('df_visual_word_total.csv', index=False)"""
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive/
!ls
df_visual_word_total = pd.read_csv('/content/drive/MyDrive/'
'df_visual_word_total.csv')
"""df_visual_word_total = pd.read_csv(
"/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC"
"/WORK-projet6/df_visual_word_total.csv")"""
im_features.shape
print("Dimensions dataset avant réduction PCA : ", im_features.shape)
pca = PCA(n_components=0.95)
feat_pca = pca.fit_transform(im_features)
print("Dimensions dataset après réduction PCA : ", feat_pca.shape)
pca = PCA(n_components=0.95, random_state=40)
pca.fit_transform(im_features)
def inertia(pca):
"""
Graph representing the eigenvalues of the pca model based on the file
under study
pca : pca of the model"""
scree = pca.explained_variance_ratio_ * 100
plt.bar(np.arange(len(scree)) + 1, scree)
plt.plot(np.arange(len(scree)) + 1, scree.cumsum(), c="red", marker="o")
plt.xlabel("rank of the axis of inertia")
plt.ylabel("percentage of inertia")
plt.title("Eigenvalue decay") # Eboulis des valeurs propres
plt.show(block=False)
plt.figure(figsize=(25, 10))
inertia(pca)
plt.figure(figsize=(16, 9))
plt.ylabel("Variance cumulée", weight='bold', size=20)
plt.xlabel('Nbr de composantes principales', weight='bold', size=17)
plt.plot(pca.explained_variance_ratio_.cumsum())
plt.title('Courbe de variances cumulées', size=18, weight='bold')
plt.plot([0, df_visual_word_total.shape[1]], [0.95, 0.95])
c = 0
for i in pca.explained_variance_ratio_.cumsum():
c += 1
if(i > 0.95):
print(
'Il faut {} composantes pour expliquer 99% de la variance du dataset'.format(c))
break
composantes = pca.components_
nbre_composantes = pca.n_components
a_show = pca.transform(im_features)[:, 0] # Component 1
b_show = pca.transform(im_features)[:, 1] # Component 2
X_pca = pca.transform(im_features)[:, :c]
sns.set_context("paper", font_scale=1.5)
plt.figure(figsize=(15, 15))
chaine = "Plan factoriel pour les composantes 1 et 2 de l'ACP"
plt.title(chaine)
plt.xlabel("Component 1")
plt.ylabel("Component 2")
ax = plt.gca()
sns.scatterplot(
x=a_show,
y=b_show,
hue=data_clean['product_category'],
alpha=0.8,
s=30
)
sns.set_context("paper", font_scale=1)
from sklearn import manifold, decomposition
tsne = TSNE(n_components=2, init='pca', random_state=6)
X_tsne = tsne.fit_transform(X_pca)
df_tsne = pd.DataFrame(X_tsne[:,0:2], columns=['tsne1', 'tsne2'])
df_tsne["class"] = final_data["category"]
print(df_tsne.shape)
plt.figure(figsize=(15,15))
sns.scatterplot(
x="tsne1", y="tsne2", hue="class", data=df_tsne, legend="brief",
palette=sns.color_palette('tab10', n_colors=7), s=50, alpha=0.6)
plt.title('TSNE selon les vraies classes', fontsize = 30, pad = 35, fontweight = 'bold')
plt.xlabel('tsne1', fontsize = 26, fontweight = 'bold')
plt.ylabel('tsne2', fontsize = 26, fontweight = 'bold')
plt.legend(prop={'size': 14})
plt.show()
km = KMeans(n_clusters=7,
init='k-means++')
silhouette, ARI, tot_data_label = clustering(
km, X_pca, final_data['category'], final_data['label_category'], 'k-means')
label = np.arange(tot_data_label['algo_cluster'].min(
), tot_data_label['algo_cluster'].max()+1, 1)
for i in range(len(label)):
df = tot_data_label.loc[tot_data_label['algo_cluster'] == label.item(i)]
cat = df['category'].unique()
print('Dans le Cluster {} on retrouve des données réparties dans les catégories {} déterminées manuellement. \n \n' .format(label.item(i), cat))
table = pd.pivot_table(tot_data_label, values='label_category', index=['category'], # , 'category'
columns=['algo_cluster'], aggfunc=lambda x: len(x), fill_value=0)
table
plt.figure(figsize=(18, 12))
plt.title('Répartition des clusters', size=20, weight='bold')
sns.set(font_scale=1.4) # for label size
sns.heatmap(table, annot=True,
cmap='BuPu',
annot_kws={"size": 15, 'weight': 'bold'},
fmt='g')
plt.ylabel("catégorie", weight='bold', size=16)
plt.xlabel('cluster', weight='bold', size=16)
plt.show()
clustering_resume = pd.DataFrame({})
clustering_resume = clustering_resume.append(
pd.DataFrame(
{
"Algorithme": "k-means",
"silhouette": silhouette,
"ARI": ARI
},
index=[0],
)
)
clustering_resume
hierarchique = AgglomerativeClustering(n_clusters=7)
silhouette, ARI, tot_data_label = clustering(
hierarchique, X_pca, final_data['category'], final_data['label_category'], 'clustering hiérarchique')
label = np.arange(tot_data_label['algo_cluster'].min(
), tot_data_label['algo_cluster'].max()+1, 1)
for i in range(len(label)):
df = tot_data_label.loc[tot_data_label['algo_cluster'] == label.item(i)]
cat = df['category'].unique()
print('Dans le Cluster {} on retrouve des données réparties dans les catégories {} déterminées manuellement. \n \n' .format(label.item(i), cat))
table = pd.pivot_table(tot_data_label, values='label_category', index=['category'], # , 'category'
columns=['algo_cluster'], aggfunc=lambda x: len(x), fill_value=0)
table
plt.figure(figsize=(18, 12))
plt.title('Répartition des clusters', size=20, weight='bold')
sns.set(font_scale=1.4) # for label size
sns.heatmap(table, annot=True,
cmap='BuPu',
annot_kws={"size": 15, 'weight': 'bold'},
fmt='g'
)
plt.ylabel("catégorie", weight='bold', size=16)
plt.xlabel('cluster', weight='bold', size=16)
plt.show()
clustering_resume = clustering_resume.append(
pd.DataFrame(
{
"Algorithme": "clustering hiérarchique",
"silhouette": silhouette,
"ARI": ARI
},
index=[1],
)
)
clustering_resume
Dans notre cas, le clustering devrait être fait par qui donne les meilleurs résultats. Mais il faut tout de même trouver un algorithme qui donnera de meilleurs résultats car ici le clustering est peu efficace.
def write_image_in_good_set(L1, L2, set_type):
"""
Pour l'utilisation de data_generator : répartition des images dans les dossiers train et test correspondants
en fonction du test_train split
"""
c = 0
for i, j in zip(L1, L2):
c += 1
# Lecture de l'image.
"""img = cv2.imread(
'/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/Flipkart/Images/{}'.format(i))"""
img = cv2.imread(
'/content/drive/MyDrive/Data_projet_OC/Flipkart/Images/{}'.format(i))
# Ecriture de l'image dans le dossier à la classe correspondante.
"""cv2.imwrite(
'/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/{0}/{1}/im{2}.jpg'.format(set_type, j, c), img)"""
# cv2.imwrite(
# '/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/{0}/im{1}.jpg'.format(set_type, c), img)
cv2.imwrite(
'/content/drive/MyDrive/Data_projet_OC/{0}/{1}/{2}'.format(set_type, j, i), img)
df = data_clean_ordered[['image', 'product_category']].copy()
df
# Split en training/testing set.
X_train, X_test, y_train, y_test = train_test_split(df['image'],
df['product_category'],
test_size=0.20,
random_state=42)
# Writting the image of the training set.
write_image_in_good_set(X_train, y_train, 'Training Set')
# Writting the image of the training set.
write_image_in_good_set(X_test, y_test, 'Testing Set')
# chargement des images
"""base_dir = '/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/'
"""
base_dir = '/content/drive/MyDrive/Data_projet_OC/'
train_dir = os.path.join(base_dir, 'Training Set')
test_dir = os.path.join(base_dir, 'Testing Set')
datagen = ImageDataGenerator(
preprocessing_function=preprocess_input) # preprocessing image
batch_size = 20
print("Training Set :")
datagen.flow_from_directory(train_dir,
class_mode='categorical')
print("\n \n")
print("Test Set :")
datagen.flow_from_directory(test_dir,
class_mode='categorical')
print("\n \n")
from google.colab import drive
y_train = pd.DataFrame(y_train)
#y_train.to_csv('y_train.csv', index=False)
# sur google colab
drive.mount('/content/drive')
y_train.to_csv('y_train_nt2.csv', index=False)
!cp y_train_nt2.csv /content/drive/My\ Drive/
y_train
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive/
!ls
y_train = pd.read_csv('/content/drive/MyDrive/'
'y_train_nt2.csv')
from google.colab import drive
y_test = pd.DataFrame(y_test)
#y_test.to_csv('y_test.csv', index=False)
# sur google colab
drive.mount('/content/drive')
y_test.to_csv('y_test_nt2.csv', index=False)
!cp y_test.csv /content/drive/My\ Drive/
y_test
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive/
!ls
y_test = pd.read_csv('/content/drive/MyDrive/'
'y_test_nt2.csv')
from google.colab import drive
X_train = pd.DataFrame(X_train)
#y_train.to_csv('y_train.csv', index=False)
# sur google colab
drive.mount('/content/drive')
X_train.to_csv('X_train_nt2.csv', index=False)
!cp X_train_nt2.csv /content/drive/My\ Drive/
X_train
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive/
!ls
X_train = pd.read_csv('/content/drive/MyDrive/'
'X_train_nt2.csv')
from google.colab import drive
y_test = pd.DataFrame(y_test)
#y_test.to_csv('y_test.csv', index=False)
# sur google colab
drive.mount('/content/drive')
X_test.to_csv('X_test_nt2.csv', index=False)
!cp X_test.csv /content/drive/My\ Drive/
X_test
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive/
!ls
X_test = pd.read_csv('/content/drive/MyDrive/'
'X_test_nt2.csv')
# Liste contenant les descripteurs.
sift_keypoints = []
"""total_list = []
path = "/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/Training Set/"
for subdir, dirs, files in os.walk(path):
for file in files:
# print os.path.join(subdir, file)
filepath = subdir + os.sep + file
if filepath.endswith(".jpg"):
total_list.append(file)"""
# Extraction des descripteurs par orb
orb = cv2.ORB_create()
classes = ["baby_care", "beauty_and_personal_care", "computers",
"home_decor_and_festive_needs", "home_furnishing", "kitchen_and_dining", "watches"]
for cat in classes:
#path = "/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/Training Set/{}/".format(cat)
path = "/content/drive/MyDrive/Data_projet_OC/Training Set/{}/".format(cat)
list_name_pictures_train = [file for file in listdir(path)]
print(cat)
print("Nombre d'images pour cette classe : {} \n \n " .format(
len(list_name_pictures_train)))
for image_num in range(len(list_name_pictures_train)):
extension = list_name_pictures_train[image_num].split('.')[-1]
if extension != "jpg":
pass
else:
image_bw = cv2.imread(
path+list_name_pictures_train[image_num], 0) # convert in grey
# convert all picture to the same size
image_bw_resized = imutils.resize(image_bw, width=400)
# Amélioration luminosité
#img_lum = autocontrast_func(image_bw_resized)
# Amélioration contraste
# image_cont = cv2.equalizeHist(img_lum) # égalisation histogramme
image_cont = cv2.equalizeHist(
image_bw_resized) # égalisation histogramme
# Débruitage
image_denoise = cv2.fastNlMeansDenoising(image_cont)
# Filtre médian
image_filtre_1 = cv2.medianBlur(image_denoise, 3)
#image_filtre_1 = cv2.medianBlur(image_cont, 3)
# filtre gausien
image_filtre_2 = cv2.GaussianBlur(image_filtre_1, (5, 5), 1)
# Keypoints & Descripteurs.
key_points, descriptors = orb.detectAndCompute(
image_filtre_2, None)
#img = cv2.drawKeypoints(i,kp,i)
sift_keypoints.append(descriptors)
sift_keypoints_by_img = np.asarray(sift_keypoints)
sift_keypoints_all = np.concatenate(sift_keypoints_by_img, axis=0)
print('\n \n Nombre de descripteurs au total pour les données train:',
sift_keypoints_all.shape[0])
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
file_name = "sift_keypoints_by_img_train.pkl"
open_file = open(file_name, "wb")
pickle.dump(sift_keypoints_by_img, open_file)
open_file.close()
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
open_file = open(file_name, "rb")
sift_keypoints_by_img = pickle.load(open_file)
open_file.close()
# print(sift_keypoints_by_img)
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
file_name1 = "sift_keypoints_all_train.pkl"
open_file1 = open(file_name1, "wb")
pickle.dump(sift_keypoints_all, open_file1)
open_file1.close()
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
open_file1 = open(file_name1, "rb")
sift_keypoints_all = pickle.load(open_file1)
open_file1.close()
# print(sift_keypoints_all)
from sklearn import cluster, metrics
# Determination number of clusters
k = int(round(np.sqrt(len(sift_keypoints_all)), 0))
print("Nombre de clusters estimés : ", k)
print("Création de", k, "clusters de descripteurs ...")
# Clustering
model = cluster.MiniBatchKMeans(
n_clusters=k, random_state=0, init='k-means++', init_size=3*k).fit(sift_keypoints_all)
# MiniBatchKMeans k-means plus rapide argument en plus : init_size=3*k
"""def clust_kmeans(k, descriptor_list):
kmeans = cluster.MiniBatchKMeans(n_clusters=k, random_state=0, init='k-means++', init_size=3*k) #MiniBatchKMeans k-means plus rapide argument en plus : init_size=3*k
kmeans.fit(descriptor_list)
visual_words = kmeans.cluster_centers_
return visual_words
visual_words = clust_kmeans(k, sift_keypoints_all)"""
"""# Creation of histograms (features)
def build_histogram(kmeans, des, image_num):
res = kmeans.predict(des)
hist = np.zeros(len(kmeans.cluster_centers_))
nb_des=len(des)
if nb_des==0 : print("problème histogramme image : ", image_num)
for i in res:
hist[i] += 1.0/nb_des
return hist
# Creation of a matrix of histograms
hist_vectors=[]
for i, image_desc in enumerate(sift_keypoints_by_img) :
if i%100 == 0 : print(i)
hist = build_histogram(kmeans, image_desc, i) #calculates the histogram
hist_vectors.append(hist) #histogram is the feature vector
im_features = np.asarray(hist_vectors)"""
# Creation of histograms (features vectors)
feature_vectors = []
for cat in classes:
#path = "/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/Training Set/{}/".format(cat)
path = "/content/drive/MyDrive/Data_projet_OC/Training Set/{}/".format(cat)
list_name_pictures_train = [file for file in listdir(path)]
print(cat)
print("Nombre d'images pour cette classe : {} \n \n " .format(
len(list_name_pictures_train)))
for image_num in range(len(list_name_pictures_train)):
extension = list_name_pictures_train[image_num].split('.')[-1]
if extension != "jpg":
pass
else:
image_bw = cv2.imread(path+list_name_pictures_train[image_num], 0)
image_bw_resized = imutils.resize(image_bw, width=400)
image_cont = cv2.equalizeHist(image_bw_resized)
image_denoise = cv2.fastNlMeansDenoising(image_cont)
image_filtre_1 = cv2.medianBlur(image_denoise, 3)
image_filtre_2 = cv2.GaussianBlur(image_filtre_1, (5, 5), 1)
# Keypoints & Descripteurs : orb extraction
key_points, descriptors = orb.detectAndCompute(
image_filtre_2, None)
# classification of all descriptors in the model
predict_kmeans = model.predict(descriptors)
# calculates the histogram
# k =int(round(np.sqrt(len(sift_keypoints_all)),0))
hist, bin_edges = np.histogram(predict_kmeans, bins=k)
# histogram is the feature vector
feature_vectors.append(hist)
im_features = np.asarray(feature_vectors)
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
file_name2 = "im_features_train.pkl"
open_file2 = open(file_name2, "wb")
pickle.dump(im_features, open_file2)
open_file2.close()
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive
!ls
open_file2 = open(file_name2, "rb")
im_features = pickle.load(open_file2)
open_file2.close()
# print(sift_keypoints_all)
df_visual_word_Xtrain = pd.DataFrame(im_features)
# sur google colab
from google.colab import drive
drive.mount('/content/drive')
df_visual_word_Xtrain.to_csv('df_visual_word_Xtrain.csv', index=False)
!cp df_visual_word_Xtrain.csv /content/drive/My\ Drive/
#df_visual_word_Xtrain.to_csv('df_visual_word_Xtrain.csv', index=False)
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive/
!ls
df_visual_word_Xtrain = pd.read_csv('/content/drive/MyDrive/'
'df_visual_word_Xtrain.csv')
"""df_visual_word_Xtrain = pd.read_csv(
"/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC"
"/WORK-projet6/df_visual_word_Xtrain.csv")"""
df_visual_word_Xtrain
# Creation of histograms (features vectors)
feature_vectors = []
for cat in classes:
#path = "/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/Testing Set/{}/".format(cat)
path = "/content/drive/MyDrive/Data_projet_OC/Testing Set/{}/".format(cat)
list_name_pictures_test = [file for file in listdir(path)]
print(cat)
print("Nombre d'images pour cette classe : {} \n \n " .format(
len(list_name_pictures_test)))
for image_num in range(len(list_name_pictures_test)):
extension = list_name_pictures_test[image_num].split('.')[-1]
if extension != "jpg":
pass
else:
image_bw = cv2.imread(path+list_name_pictures_test[image_num], 0)
image_bw_resized = imutils.resize(image_bw, width=400)
image_cont = cv2.equalizeHist(image_bw_resized)
image_denoise = cv2.fastNlMeansDenoising(image_cont)
image_filtre_1 = cv2.medianBlur(image_denoise, 3)
image_filtre_2 = cv2.GaussianBlur(image_filtre_1, (5, 5), 1)
# Keypoints & Descripteurs : orb extraction
key_points, descriptors = orb.detectAndCompute(
image_filtre_2, None)
# classification of all descriptors in the model
predict_kmeans = model.predict(descriptors)
# calculates the histogram
# k =int(round(np.sqrt(len(sift_keypoints_all)),0))
hist, bin_edges = np.histogram(predict_kmeans, bins=k)
# histogram is the feature vector
feature_vectors.append(hist)
im_features = np.asarray(feature_vectors)
file_name2 = "im_features_test.pkl"
open_file2 = open(file_name2, "wb")
pickle.dump(im_features, open_file2)
open_file2.close()
open_file2 = open(file_name2, "rb")
im_features = pickle.load(open_file2)
open_file2.close()
# print(sift_keypoints_all)
df_visual_word_Xtest = pd.DataFrame(im_features)
# sur google colab
from google.colab import drive
drive.mount('/content/drive')
df_visual_word_Xtest.to_csv('df_visual_word_Xtest.csv', index=False)
!cp df_visual_word_Xtest.csv /content/drive/My\ Drive/
"""df_visual_word_Xtest.to_csv('df_visual_word_Xtest.csv', index=False)"""
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My\ Drive/
!ls
data = pd.read_csv('/content/drive/MyDrive/'
'df_visual_word_Xtest.csv')
"""df_visual_word_Xtest = pd.read_csv(
"/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC"
"/WORK-projet6/df_visual_word_Xtest.csv")"""
df_visual_word_Xtest
df_visual_word_Xtrain.shape
pca = PCA(n_components=df_visual_word_Xtrain.shape[1], random_state=40)
pca.fit_transform(df_visual_word_Xtrain)
X_pca_train = pca.transform(df_visual_word_Xtrain)[:, :c]
X_pca_test = pca.transform(df_visual_word_Xtest)[:, :c]
# GridSearch
# create new a knn model
knn2 = KNeighborsClassifier()
# create a dictionary of all values we want to test for n_neighbors
param_grid = {'n_neighbors': np.arange(1, 25)}
score = 'accuracy'
# use gridsearch to test all values for n_neighbors
knn_gscv = GridSearchCV(knn2, param_grid, cv=5)
# Fit sur le training set.
knn_gscv.fit(X_pca_train, y_train)
# Afficher le(s) hyperparamètre(s) optimaux
best_param = knn_gscv.best_estimator_
print("Best paramètres: {}".format(best_param))
# Afficher les performances correspondantes
print("Résultats de la validation croisée :")
for mean, std, params in zip(
knn_gscv.cv_results_['mean_test_score'], # score moyen
knn_gscv.cv_results_['std_test_score'], # écart-type du score
knn_gscv.cv_results_['params'] # valeur de l'hyperparamètre
):
print("{} = {:.3f} (+/-{:.03f}) for {}".format(
score,
mean,
std*2,
params
))
accuracy, precision, recall, f1, resume_class = classification(
best_param, X_pca_train, y_train, X_pca_test, y_test, 'knn')
Ici le score d'accuracy est de 0.109 ce qui montre que la classification fonctionne très mal.
Ici le score de précision est de 0.112 montre que la prédiction est très peu précise car le score est proche de 0.
Ici le score de recall est de 0.109 montre que la prédiction ne fait pas en majorité des vrais positifs car le score est proche de 0.
Les labels des catégories prédites correspondent aux labels des catégories réelles pour les donnéees test. On peut voir que pour les catégories 1, 3, 4, 5 et 6, la classification regroupe moins de produits dans ces catégorie par rapport à la réalité. La conclusion inverse peut être faîte pour les catégories 0 et 2.
Les articles sont surtout regroupés dans les catégories 0, 2.
classification_resume = pd.DataFrame({})
classification_resume = classification_resume.append(
pd.DataFrame(
{
"Algorithme": "knn",
"accuracy": accuracy,
"precision": precision,
"recall": recall,
"f1_score": f1
},
index=[0],
)
)
classification_resume
# GridSearch
param_grid = [{'max_depth': range(2, 10, 2)}]
gridSearch = GridSearchCV(RandomForestClassifier(),
param_grid, cv=5, scoring='accuracy')
score = 'accuracy'
# Fit sur le training set.
gridSearch.fit(X_pca_train, y_train)
# Afficher le(s) hyperparamètre(s) optimaux
best_param = gridSearch.best_estimator_
print("Best paramètres: {}".format(best_param))
# Afficher les performances correspondantes
print("Résultats de la validation croisée :")
for mean, std, params in zip(
gridSearch.cv_results_['mean_test_score'], # score moyen
gridSearch.cv_results_['std_test_score'], # écart-type du score
gridSearch.cv_results_['params'] # valeur de l'hyperparamètre
):
print("{} = {:.3f} (+/-{:.03f}) for {}".format(
score,
mean,
std*2,
params
))
accuracy, precision, recall, f1, resume_class = classification(
best_param, X_pca_train, y_train, X_pca_test, y_test, 'Random Forest')
Ici le score d'accuracy est de 0.15 ce qui montre que la classification fonctionne mal.
Ici le score de précision est de 0.13 montre que la prédiction est peu précise car le score est proche de 1.
Ici le score de recall est de 0.15 montre que la prédiction ne fait pas en majorité des vrais positifs car le score est proche de 0.
Les labels des catégories prédites correspondent aux labels des catégories rélles pour les donnéees test. On peut voir aussi que pour les catégories 1, 3, 4 et 6 la classification regroupe moins de produits dans ces catégorie par rapport à la réalité. La conclusion inverse peut être faîte pour les catégories 0, 2 et 5.
classification_resume = classification_resume.append(
pd.DataFrame(
{
"Algorithme": "Random Forest",
"accuracy": accuracy,
"precision": precision,
"recall": recall,
"f1_score": f1
},
index=[1],
)
)
classification_resume
Avec une classification standard, nous avons de très mauvais résultats. Voyons si avec un réseau de neurones covolutif adapté à la classification des images nous donne de meilleurs résultats.
deep learning : type d'apprentissage automatique basé sur des réseaux neuronaux artificiels dans lesquels plusieurs couches de traitement sont utilisées pour extraire des données des caractéristiques.
Le transfert learning utilise des modèles pré-entraînés comme point de départ, il permet de développer rapidement des modèles performants et résoudre efficacement des problèmes complexes en Computer Vision ou Natural Language Processing, NLP.
Le Transfer Learning repose sur une idée simple, celle de ré-exploiter les connaissances acquises dans d’autres configurations (sources) pour la résolution d’un problème particulier (cible).
CNN (réseau de neurones par convolution) est un empilement de couches de neurones qui utilise un modèles pré-entraîné comme extracteurs de features. Ces couches apprennent différentes caractéristiques en fonction du niveau où elles se situent. Plus la couche se situe en profondeur, plus elle permet d’extraire des features spécifiques.
Ici, transfer learning via le réseau VGG16 pré-entrainé sur une base d'images riches (imagenet). Le VGG-16 (Very Deep Convolutional Networks for Large-Scale Image Recognition, 16 couches) est l'un des modèles pré-entraînés les plus populaires pour la classification des images.
new_model = Sequential()
# Charger VGG-16 pré-entraîné sur ImageNet et sans les couches fully-connected (couches hautes).
model = VGG16(weights="imagenet", include_top=False, input_shape=(224, 224, 3))
#On entraîne seulement le nouveau classifieur et on ne ré-entraîne pas les autres couches :
for layer in model.layers:
layer.trainable = False
new_model.add(model)
# Ajout d'une couche Flatten pour réduire les dimensions de l'input.
new_model.add(Flatten())
# Ajout de la couche Dense de prédiciton adaptée à notre problème de classifications (7 classes).
new_model.add(Dense(7, activation='softmax'))
# réseau de neurones
new_model.summary()
En résumé, le VGG-16 contient 16 couches où le nombre de caractéristiques est de 25 088 (flatten) après l'aplatissement de la dernière couche convolutive (la 1ère mise en évidence) et dans la couche finale (prédiction ou couche dense finale), le nombre de nœuds est de 7 car le VGG-16 est principalement entraîné pour un problème de classification de 7 classes (la 2ème mise en évidence) (prédiction).
# Compilation du modèle
new_model.compile(loss="categorical_crossentropy", optimizer=optimizers.SGD(
lr=0.0001, momentum=0.9), metrics=["accuracy"])
batch_size = 32
categorical_crossentropy quand nombre de cat>2 sinon binary_crossentropy
# Path du dossier.
#folder = "/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/Testing Set"
folder = "/content/drive/MyDrive/Data_projet_OC/Testing Set"
i = 0
# Liste contenant les catégories des images chargées
y_test_category = []
for j in os.listdir(folder):
folder_courant = folder + '/' + j
for filename in os.listdir(folder_courant):
y_test_category.append(j)
# Path du fichier.
path = folder_courant + '/' + filename
# Charger l'image à la bonne dimension.
img_resize = load_img(path, target_size=(224, 224))
# Transformation de l'image en tableau numpy.
img = img_to_array(img_resize)
img = img.reshape((1, img.shape[0], img.shape[1], img.shape[2]))
# Preprocessing.
img = preprocess_input(img)
# Ajout de l'image à la liste de stockage.
if (i == 0):
x1 = img
i = 1
else:
x1 = np.concatenate((x1, img), axis=0)
# Training Augmentation configuration
#base_dir = '/Users/amandinelecerfdefer/Desktop/Formation_Data_Scientist_OC/WORK-projet6/Data/'
base_dir = '/content/drive/MyDrive/Data_projet_OC/'
train_dir = os.path.join(base_dir, 'Training Set')
test_dir = os.path.join(base_dir, 'Testing Set')
train_datagen = ImageDataGenerator(rescale=1./255,
zoom_range=0.2,
preprocessing_function=preprocess_input)
# Testing Augmentation
test_datagen = ImageDataGenerator(rescale=1./255,
zoom_range=0.2,
preprocessing_function=preprocess_input)
# Generates batches of Augmented Image data
train_generator = train_datagen.flow_from_directory(train_dir, target_size=(224, 224),
batch_size=batch_size,
class_mode='categorical')
# Generator for validation data
validation_generator = test_datagen.flow_from_directory(test_dir,
target_size=(224, 224),
batch_size=batch_size,
class_mode='categorical')
# Fit the model on Training data
history = new_model.fit_generator(train_generator,
epochs=5,
validation_data=validation_generator,
verbose=1)
with open('/trainHistoryDict', 'wb') as file_pi:
pickle.dump(history.history, file_pi)
# Entraînement du modèle via le train_generator.
# On fait attention à l'overfitting en utilisant notre validation set.
# fit_generator fait la même chose que fit mais fit_generator est mieux adapté au nombreuse données
new_model.save("CNN_pictures_model")
une epoch : une passe avant et une passe arrière de tous les exemples d'entraînement
batch size : nombre d'échantillons qui seront propagés dans le réseau. 1050 échantillons d'entraînement et vous souhaitez définir une taille de lot égale à 100.
L'algorithme prend les 100 premiers échantillons (du 1er au 100e) de l'ensemble de données d'apprentissage et entraîne le réseau.
Ensuite, il prend les 100 autres échantillons (du 101e au 200e) et entraîne à nouveau le réseau.
steps_per_epochs : nombre d'itérations de lot avant qu'une époque d'apprentissage soit considérée comme terminée : steps_per_epoch = len(X_train)//batch_size
plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label='val_accuracy')
plt.plot(history.history['loss'], label='loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
#plt.ylim([0.5, 1])
plt.legend(loc='lower right')
fit() sert à entraîner le modèle avec les entrées données (et les étiquettes d'entraînement correspondantes).
evaluate() permet d'évaluer le modèle déjà formé en utilisant les données de validation (ou de test) et les étiquettes correspondantes. Elle renvoie la valeur de perte et les valeurs métriques du modèle.
predict() sert à la prédiction proprement dite. Elle génère des prédictions de sortie pour les échantillons d'entrée.
# Évaluation de la performance du modèle sur des données de test
loss, accuracy = new_model.evaluate(validation_generator)
print("\nModel's Evaluation Metrics: ")
print("---------------------------")
print("Accuracy: {} \nLoss: {}".format(accuracy, loss))
Le CNN a atteint une précision de prédiction de plus de 72%
# Prediction sur le testing Set.
pred = new_model.predict(x1, verbose=1)
pred
y_classes = [np.argmax(element) for element in pred]
y_classes[:5]
df = pd.DataFrame(y_classes, columns=['predict_category'])
df
dico_categ = {0: 'baby_care',
1: 'beauty_and_personal_care',
2: 'computers',
3: 'home_decor_and_festive_needs',
4: 'home_furnishing',
5: 'kitchen_and_dining',
6: 'watches'}
df = df.replace({"predict_category": dico_categ})
df
df1 = pd.DataFrame(y_test_category, columns=['product_category'])
df1['product_category'] = df1['product_category'].str.replace(
"'", '')
df1
resume_cnn = pd.concat([df, df1], axis=1)
resume_cnn
# Qualité de la classification
accuracy = accuracy_score(
resume_cnn['product_category'], resume_cnn['predict_category'])
print('L\'accuracy score est de {} \n \n '.format(
accuracy))
precision = precision_score(
resume_cnn['product_category'], resume_cnn['predict_category'], average='weighted')
print('La score précision est de {} \n \n '.format(
precision))
recall = recall_score(resume_cnn['product_category'],
resume_cnn['predict_category'], average='weighted')
print('Le score recall est de {} \n \n '.format(
recall))
f1 = f1_score(resume_cnn['product_category'],
resume_cnn['predict_category'], average='weighted')
print('Le score f1 est de {} \n \n '.format(
f1))
Ici le score d'accuracy est de 0.58 ce qui montre que la classification fonctionne bien avec une grande précision.
Ici le score de précision est de 0.64 montre que la prédiction est assez précise car le score est proche de 1.
Ici le score f1 est de 0.56 montre que la prédiction fait en majorité des vrais positifs car le score est proche de 1.
le = preprocessing.LabelEncoder()
resume_cnn['label_cat_reel'] = le.fit_transform(
np.array(resume_cnn['product_category']))
resume_cnn['label_cat_predit'] = le.transform(
np.array(resume_cnn['predict_category']))
resume_cnn
plt.figure(figsize=(10, 10))
plt.title('Répartition des catégories après classification \n \n ',
fontsize=18, fontweight="bold")
sns.distplot(resume_cnn['label_cat_reel'], bins=20, rug=True)
sns.distplot(resume_cnn['label_cat_predit'], bins=20, rug=True)
plt.xlabel("Catégories")
plt.legend(['reel', 'prediction'])
from matplotlib import cm
fig = plt.figure(figsize=(30, 15))
ax1 = plt.subplot(121)
ax2 = plt.subplot(122)
nb_label_real = resume_cnn['product_category'].nunique()
cs_nb_label_real = cm.Set2(np.arange(nb_label_real))
nb_label_predit = resume_cnn['predict_category'].nunique()
cs_nb_label_predit = cm.Set2(np.arange(nb_label_predit))
ax1 = resume_cnn.groupby('product_category').count().plot(kind='pie',
y='label_cat_reel',
ax=ax1,
legend=False,
shadow=True,
startangle=0,
autopct='%1.1f%%',
textprops={
'fontsize': 26},
colors=cs_nb_label_real)
ax1.axis('equal')
ax1.set_xlabel("classes réelles", fontsize=22)
ax1.set_ylabel(" ")
ax2 = resume_cnn.groupby('predict_category').count().plot(kind='pie',
y='label_cat_predit',
ax=ax2,
legend=False,
shadow=True,
startangle=0,
autopct='%1.1f%%',
textprops={
'fontsize': 26},
colors=cs_nb_label_predit)
ax2.axis('equal')
ax2.set_xlabel("classes prédites par CNN", fontsize=22)
ax2.set_ylabel(" ")
plt.suptitle('Répartition des produits (test data) entre les différentes catégories déterminées',
fontsize=30)
plt.subplots_adjust(wspace=1.5)
plt.show()
Les labels des catégories prédites correspondent aux labels des catégories réelles pour les donnéees test. Avec ce graphique, on peut voir que les catégories prédites sont proches de la classification manuelle. On peut voir aussi que pour les catégories 2, 4 et 5, le CNN regroupe moins de produits dans ces catégories par rapport à la réalité. La conclusion inverse peut être faîte pour les catégories 0, 3, 1 et 6.
cf_matrix = confusion_matrix(
resume_cnn["product_category"], resume_cnn["predict_category"], normalize='true')
plt.figure(figsize=(18, 12))
plt.title('Matrice de confusion', size=20, weight='bold')
sns.set(font_scale=1.4) # for label size
sns.heatmap(cf_matrix, annot=True,
fmt='.2%', cmap='BuPu',
annot_kws={"size": 15, 'weight': 'bold'})
plt.ylabel("Vraie catégorie", weight='bold', size=20)
plt.xlabel('Prediction', weight='bold', size=17)
plt.show()
L'algorithme se trompe surtout sur la prédiction des catégories 2 et 4.
Le clustering trouve bien des clusters pour séparer les données, il peut également être intéressant de voir l'effet d'une classification.
Les algorithmes les mieux adaptés à nos données pour une classification est l'algorithmes du CNN qui nous donne les meilleurs résultats.
Pour le Clustering, il s'agit de l'algorithme du K-means qui nous donne les meilleurs résultats.
Cependant, on peut dire que le CNN, pour l'extraction de features es imagesest plus performant que la méthode SIFT/ORB.
# GridSearch
# create new a knn model
knn2 = KNeighborsClassifier()
# create a dictionary of all values we want to test for n_neighbors
param_grid = {'n_neighbors': np.arange(1, 25)}
score = 'accuracy'
# use gridsearch to test all values for n_neighbors
knn_gscv = GridSearchCV(knn2, param_grid, cv=5)
# Fit sur le training set.
knn_gscv.fit(df_visual_word_Xtrain, y_train)
# Afficher le(s) hyperparamètre(s) optimaux
best_param = knn_gscv.best_estimator_
print("Best paramètres: {}".format(best_param))
# Afficher les performances correspondantes
print("Résultats de la validation croisée :")
for mean, std, params in zip(
knn_gscv.cv_results_['mean_test_score'], # score moyen
knn_gscv.cv_results_['std_test_score'], # écart-type du score
knn_gscv.cv_results_['params'] # valeur de l'hyperparamètre
):
print("{} = {:.3f} (+/-{:.03f}) for {}".format(
score,
mean,
std*2,
params
))
best_param = KNeighborsClassifier()
accuracy, precision, recall, f1, resume_class = classification(
best_param, df_visual_word_Xtrain, y_train, df_visual_word_Xtest, y_test, 'knn')
Ici le score d'accuracy est de 0.13 ce qui montre que la classification fonctionne très mal.
Ici le score de précision est de 0.12 montre que la prédiction est très peu précise car le score est proche de 0.
Ici le score de recall est de 0.13 montre que la prédiction ne fait pas en majorité des vrais positifs car le score est proche de 0.
Les labels des catégories prédites correspondent aux labels des catégories réelles pour les donnéees test. On peut voir que pour les catégories 1, 2, 3, 4 et 6, la classification regroupe moins de produits dans ces catégories par rapport à la réalité. La conclusion inverse peut être faîte pour les catégories 0 et 5.
Les produits se regroupe surtout dans les catégories 0 et 5
classification_resume_sans_pca = pd.DataFrame({})
classification_resume_sans_pca = classification_resume_sans_pca.append(
pd.DataFrame(
{
"Algorithme": "knn",
"accuracy": accuracy,
"precision": precision,
"recall": recall,
"f1_score": f1
},
index=[0],
)
)
classification_resume_sans_pca
# GridSearch
param_grid = [{'max_depth': range(2, 10, 2)}]
gridSearch = GridSearchCV(RandomForestClassifier(),
param_grid, cv=5, scoring='accuracy')
score = 'accuracy'
# Fit sur le training set.
gridSearch.fit(df_visual_word_Xtrain, y_train)
# Afficher le(s) hyperparamètre(s) optimaux
best_param = gridSearch.best_estimator_
print("Best paramètres: {}".format(best_param))
# Afficher les performances correspondantes
print("Résultats de la validation croisée :")
for mean, std, params in zip(
gridSearch.cv_results_['mean_test_score'], # score moyen
gridSearch.cv_results_['std_test_score'], # écart-type du score
gridSearch.cv_results_['params'] # valeur de l'hyperparamètre
):
print("{} = {:.3f} (+/-{:.03f}) for {}".format(
score,
mean,
std*2,
params
))
best_param = RandomForestClassifier(random_state=40)
accuracy, precision, recall, f1, resume_class = classification(
best_param, df_visual_word_Xtrain, y_train, df_visual_word_Xtest, y_test, 'Random Forest')
Ici le score d'accuracy est de 0.15 ce qui montre que la classification fonctionne mal.
Ici le score de précision est de 0.15 montre que la prédiction est peu précise car le score est proche de 1.
Ici le score de recall est de 0.15 montre que la prédiction ne fait pas en majorité des vrais positifs car le score est proche de 0.
Les labels des catégories prédites correspondent aux labels des catégories réelles pour les donnéees test. Avec ce graphique, on peut voir que les catégories prédites sont proches de la classification manuelle. On peut voir aussi que pour les catégories 1, 4, 5 et 6 la classification regroupe moins de produits dans ces catégorie par rapport à la réalité. La conclusion inverse peut être faîte pour les catégories 0, 2 et 3.
L'algorithme se trompe sur toutes les prédictions. L'attribution d'une classe est donc dûe au hasard.
classification_resume_sans_pca = classification_resume_sans_pca.append(
pd.DataFrame(
{
"Algorithme": "Random Forest",
"accuracy": accuracy,
"precision": precision,
"recall": recall,
"f1_score": f1
},
index=[1],
)
)
classification_resume_sans_pca